package com.zyf.project.binaryproto.contract.impl;

import com.zyf.project.binaryproto.annotation.DataContract;
import com.zyf.project.binaryproto.annotation.DataField;
import com.zyf.project.binaryproto.annotation.EnumContract;
import com.zyf.project.binaryproto.annotation.EnumField;
import com.zyf.project.binaryproto.codec.NumberEncoding;
import com.zyf.project.binaryproto.contract.DataContractEncoder;
import com.zyf.project.binaryproto.contract.DataContractEncoderLookup;
import com.zyf.project.binaryproto.converter.DynamicValueConverter;
import com.zyf.project.binaryproto.converter.FixedValueConverter;
import com.zyf.project.binaryproto.converter.ValueConverter;
import com.zyf.project.binaryproto.converter.impl.AbstractNumberEncodingConverter;
import com.zyf.project.binaryproto.converter.impl.dynamic.*;
import com.zyf.project.binaryproto.converter.impl.fixed.*;
import com.zyf.project.binaryproto.converter.impl.fixed.wrapper.*;
import com.zyf.project.binaryproto.encoder.FieldEncoder;
import com.zyf.project.binaryproto.encoder.impl.*;
import com.zyf.project.binaryproto.encoder.impl.dynamic.*;
import com.zyf.project.binaryproto.encoder.impl.fixed.*;
import com.zyf.project.binaryproto.exception.DataContractException;
import com.zyf.project.binaryproto.specification.BinarySliceSpecification;
import com.zyf.project.binaryproto.specification.DataSpecification;
import com.zyf.project.binaryproto.specification.EnumSpecification;
import com.zyf.project.binaryproto.specification.FieldSpecification;
import com.zyf.project.binaryproto.specification.impl.DataSpecificationInfo;
import com.zyf.project.binaryproto.specification.impl.EnumSpecificationInfo;
import com.zyf.project.binaryproto.specification.impl.FieldSpecificationInfo;
import com.zyf.project.binaryproto.type.PrimitiveType;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import utils.binary.BytesSerializable;
import utils.binary.BytesUtils;
import utils.io.NumberMask;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

/**
 * <h1>数据契约环境</h1>
 * <p>这个类是处理数据契约的核心实现之一，主要负责编码器的检索和注册</p>
 * <p>
 * 编码器的检索相关函数为
 *     <ul>
 *         <li>{@link #lookup(Class)}</li>
 *         <li>{@link #lookup(int, long)}</li>
 *         <li>{@link #isDataContractType(Class)}</li>
 *     </ul>
 * </p>
 * <p>
 *     编码器的注册相关函数为：{@link #register(Class, Function)}
 * </p>
 * <p>编码器注册的辅助函数有很多，调用顺序图如下：</p>
 * <p>
 *     -{@link #register}<br>
 *     -|>{@link #resolveContract(Class, Function)}<br>
 *     -|-|>{@link #resolveEncoder}<br>
 *     -|-|-|>{@link #resolveContractFields}<br>
 *     -|-|-|-|>{@link #resolveFieldSpecification}<br>
 *     -|-|-|-|-|>{@link #resolveContract(Class)}<br>
 *     -|-|-|-|-|>{@link #resolveEnumContract}<br>
 *     -|-|-|-|-|>{@link #verifyPrimitiveType}<br>
 *     -|-|-|-|>{@link #computeExtensionDistance}<br>
 *     -|-|-|>{@link #buildSlice}<br>
 *     -|-|-|>{@link #buildFieldEncoder}<br>
 *     -|-|-|>{@link #generateFieldTypeCode}<br>
 *     -|-|-|>{@link #hash256()}<br>
 * </p>
 * <p>注：有几个 “|” 表示在第几层被调用</p>
 *
 * @author Zhou Yifan
 */
public class DataContractContext implements DataContractEncoderLookup {

    /**
     * 互斥锁
     */
    private static final Object MUTEX = new Object();

    /**
     * 头部片段，包含了 code 和 version
     */
    private static final BinarySliceSpecification HEAD_SLICE
            = BinarySliceSpecification.newFixedSlice(
            HeaderEncoder.HEAD_BYTES,
            "HEAD",
            "The code and version of data contract"
    );

    private static final byte SINGLE_TYPE = 0;

    private static final byte REPEATABLE_TYPE = 1;

    /**
     * 基本类型的字段；
     */
    private static final byte PRIMITIVE_TYPE_FIELD = 0;
    /**
     * 枚举类型的字段；
     */
    private static final byte ENUM_CONTRACT_FIELD = 1;
    /**
     * 引用一个具体的数据契约类型的字段；
     */
    private static final byte DATA_CONTRACT_FIELD = 2;
    /**
     * 动态的数据契约类型的字段；
     */
    private static final byte DYNAMIC_CONTRACT_FIELD = 3;

    /**
     * <h2>基本类型字段的类型和值转换器 Map，这是一个 {@link EnumMap}</h2>
     * <ul>
     *     <li><b>key: </b>{@link PrimitiveType}</li>
     *     <li>
     *         <b>value: </b>{@link EnumMap}
     *         <ul>
     *             <li><b>map-key: </b>{@link Class}</li>
     *             <li><b>map-value: </b>{@link ValueConverter}</li>
     *         </ul>
     *     </li>
     * </ul>
     */
    private Map<PrimitiveType, Map<Class<?>, ValueConverter>> primitiveTypeConverters = new EnumMap<>(PrimitiveType.class);

    /**
     * <h2>数值编码类型和值转换器 Map，这是一个 {@link EnumMap}</h2>
     * <ul>
     *     <li><b>key: </b>{@link PrimitiveType}</li>
     *     <li>
     *         <b>value: </b>{@link HashMap}
     *         <ul>
     *             <li><b>map-key: </b>{@link Class}</li>
     *             <li>
     *                 <b>map-value: </b>{@link EnumMap}
     *                 <ul>
     *                     <li><b>map-value-key: </b>{@link NumberMask}</li>
     *                     <li><b>map-value-value: </b>{@link ValueConverter}</li>
     *                 </ul>
     *             </li>
     *         </ul>
     *     </li>
     * </ul>
     */
    private Map<PrimitiveType, Map<Class<?>, Map<NumberMask, ValueConverter>>> numberEncodingConverters = new EnumMap<>(PrimitiveType.class);

    private Map<Integer, ContractTypeVersionContext> codeMap = new ConcurrentHashMap<>();

    private Map<Class<?>, DataContractEncoder> typeMap = new ConcurrentHashMap<>();

    private Map<Class<?>, EnumSpecification> enumSpecificationMap = new ConcurrentHashMap<>();

    public DataContractContext() {
        initPrimitiveConverters();
    }

    /**
     * 初始化基本类型字段的值转换器
     */
    private void initPrimitiveConverters() {
        /* 添加布尔类型值转换器 */
        addConverterMapping(PrimitiveType.BOOLEAN, boolean.class, new BoolConverter());
        addConverterMapping(PrimitiveType.BOOLEAN, Boolean.class, new BoolWrapperConverter());
        /* 添加数字类型值转换器 */
        // 比特类型
        addConverterMapping(PrimitiveType.INT8, byte.class, new Int8ByteConverter());
        addConverterMapping(PrimitiveType.INT8, Byte.class, new Int8ByteWrapperConverter());
        // 短整数类型
        addConverterMapping(PrimitiveType.INT16, short.class, new Int16ShortConverter());
        addConverterMapping(PrimitiveType.INT16, Short.class, new Int16ShortWrapperConverter());
        // 字符类型
        addConverterMapping(PrimitiveType.INT16, char.class, new Int16CharConverter());
        addConverterMapping(PrimitiveType.INT16, Character.class, new Int16CharWrapperConverter());
        // 整数类型
        addConverterMapping(PrimitiveType.INT32, int.class, new Int32IntConverter());
        addConverterMapping(PrimitiveType.INT32, Integer.class, new Int32IntWrapperConverter());
        // 长整数类型
        addConverterMapping(PrimitiveType.INT64, long.class, new Int64LongConverter());
        addConverterMapping(PrimitiveType.INT64, long.class, new Int64LongWrapperConverter());
        /* 添加字符串类型值转换器 */
        addConverterMapping(PrimitiveType.TEXT, String.class, new StringValueConverter());
        /* 添加字符数组类型值转换器 */
        addConverterMapping(PrimitiveType.BYTES, byte[].class, new BytesValueConverter());
    }

    /**
     * 将 converterMap 加入到 {@link #primitiveTypeConverters} 中
     *
     * @param protoType                   数据契约的类型
     * @param javaType                    对应的 java 类
     * @param converter                   值转换器，用于编码解码
     * @param numberEncodingConverterType 数值编码格式类型，这个参数对象需要继承 {@link AbstractNumberEncodingConverter}
     */
    private synchronized void addConverterMapping(
            PrimitiveType protoType,
            Class<?> javaType,
            ValueConverter converter,
            Class<? extends AbstractNumberEncodingConverter> numberEncodingConverterType
    ) {
        addConverterMapping(protoType, javaType, converter);
        initNumberEncodingConverterMapping(protoType, javaType, numberEncodingConverterType);
    }

    /**
     * <p>将 converterMap 加入到 {@link #primitiveTypeConverters} 中</p>
     * <p>该操作加锁 synchronized</p>
     *
     * @param protoType 数据契约的类型
     * @param javaType  对应的 java 类
     * @param converter 值转换器，用于编码解码
     */
    private synchronized void addConverterMapping(
            PrimitiveType protoType,
            Class<?> javaType,
            ValueConverter converter
    ) {
        // 如果这个 key 不存在，那么就加入到 primitiveTypeConverters 中
        Map<Class<?>, ValueConverter> converterMap = primitiveTypeConverters.computeIfAbsent(protoType, k -> new HashMap<>());
        converterMap.put(javaType, converter);
    }

    /**
     * 初始化数值编码的类型和值转换器 Map，操作对象是 {@link #numberEncodingConverters}
     *
     * @param protoType                   数据契约类型
     * @param javaType                    对应的 java 类
     * @param numberEncodingConverterType 数值编码值转换器，这个参数对象需要继承 {@link AbstractNumberEncodingConverter}
     */
    private void initNumberEncodingConverterMapping(
            PrimitiveType protoType,
            Class<?> javaType,
            @NotNull Class<? extends AbstractNumberEncodingConverter> numberEncodingConverterType
    ) {
        // 如果这个 key 不存在，那么就加入到 numberEncodingConverters 中
        Map<Class<?>, Map<NumberMask, ValueConverter>> converterMap = numberEncodingConverters.computeIfAbsent(protoType, k -> new HashMap<>());
        Map<NumberMask, ValueConverter> converters = new EnumMap<>(NumberMask.class);
        converterMap.put(javaType, converters);

        try {
            Constructor<? extends ValueConverter> constructor
                    = numberEncodingConverterType.getConstructor(NumberMask.class);
            for (NumberMask numberMask : NumberMask.values()) {
                ValueConverter converter = constructor.newInstance(numberMask);
                converters.put(numberMask, converter);
            }
        } catch (InvocationTargetException
                 | NoSuchMethodException
                 | InstantiationException
                 | IllegalAccessException e) {
            throw new DataContractException(e.getMessage(), e);
        }
    }

    /**
     * 检索指定类型的编码器；
     *
     * @param contractType 指定类型
     * @return {@link DataContractEncoder}
     */
    @Override
    public DataContractEncoder lookup(Class<?> contractType) {
        return typeMap.get(contractType);
    }

    /**
     * 检索指定 code 和 version 的编码器；
     *
     * @param code    指定编码
     * @param version 指定版本
     * @return {@link DataContractEncoder}
     */
    @Override
    public DataContractEncoder lookup(int code, long version) {
        ContractTypeVersionContext ctx = codeMap.get(code);
        if (ctx == null) {
            return null;
        }
        // TODO: 未实现多个版本的处理
        return ctx.contractEncoder;
    }

    /**
     * 判断指定的类型是否声明为 {@link DataContract}
     *
     * @param contractType 指定类型
     * @return 布尔值
     */
    public static boolean isDataContractType(@NotNull Class<?> contractType) {
        if (!contractType.isInterface()) {
            return false;
        }
        DataContract annoContract = contractType.getAnnotation(DataContract.class);
        return annoContract != null;
    }

    /**
     * <p>根据数据契约类型以及构造函数列表，进行数据契约的注册</p>
     * <p>该方法调用了 {@link #resolveContract(Class, Function)}</p>
     * <p>该方法被 {@link com.zyf.project.binaryproto.common.DataContractRegistry#register(Class, Function)} 调用</p>
     *
     * @param contractType     数据契约类型
     * @param arrayConstructor 构造函数列表
     * @return {@link DataContractEncoder}
     */
    public DataContractEncoder register(Class<?> contractType, Function<Integer, ?> arrayConstructor) {
        DataContractEncoder encoder = typeMap.get(contractType);
        if (encoder != null) {
            return encoder;
        }
        synchronized (MUTEX) {
            encoder = typeMap.get(contractType);
            if (encoder != null) {
                return encoder;
            }
            ContractTypeVersionContext ctx = resolveContract(contractType, arrayConstructor);
            encoder = ctx.contractEncoder;
        }
        return encoder;
    }

    /**
     * <p>解析数据契约类型环境</p>
     * <p>这是 {@link #resolveContract(Class, Function)} 的一个重构</p>
     *
     * @param contractType 数据契约类型
     * @return {@link ContractTypeVersionContext}
     */
    private @NotNull ContractTypeVersionContext resolveContract(Class<?> contractType) {
        return resolveContract(contractType, null);
    }

    /**
     * <p>解析数据契约类型</p>
     * <p>该方法调用了 {@link #resolveEncoder(Class, DataContract, Function)}</p>
     *
     * @param contractType     数据契约类型
     * @param arrayConstructor 构造函数列表
     * @return {@link ContractTypeVersionContext}
     */
    private @NotNull ContractTypeVersionContext resolveContract(@NotNull Class<?> contractType, Function<Integer, ?> arrayConstructor) {
        // TODO: 未处理可能存在的循环依赖问题，这导致解析方法陷入死循环
        if (!contractType.isInterface()) {
            throw new IllegalArgumentException(
                    "The specified contractType [" + contractType + "] is not a interface!"
            );
        }
        DataContract annoContract = contractType.getAnnotation(DataContract.class);
        if (annoContract == null) {
            throw new IllegalArgumentException(
                    "Class[" + contractType + "] isn't annotated as DataContract!"
            );
        }
        int contractCode = annoContract.code();
        ContractTypeVersionContext ctx = codeMap.get(contractCode);
        if (ctx != null) {
            if (ctx.contractType == contractType) {
                return ctx;
            } else {
                throw new IllegalStateException(String.format(
                        "Contract Code[%s] has been registered by type[%s]! Can't register again with type[%s]!",
                        contractCode, ctx.contractType.getName(), contractType.getName()
                ));
            }
        }

        DataContractEncoder contractEncoder = resolveEncoder(contractType, annoContract, arrayConstructor);

        ctx = new ContractTypeVersionContext(contractType, contractEncoder);

        codeMap.put(contractCode, ctx);
        typeMap.put(contractType, contractEncoder);

        return ctx;
    }

    /**
     * <p>解析数据契约的二进制编码器</p>
     * <p>
     * 这个方法调用了
     *     <ul>
     *         <li>{@link #resolveContractFields(Class, DataContract)}</li>
     *         <li>{@link #buildSlice(FieldSpecificationInfo)}</li>
     *         <li>{@link #buildFieldEncoder(FieldDeclaredInfo, BinarySliceSpecification)}</li>
     *         <li>{@link #generateFieldTypeCode(FieldSpecificationInfo)}</li>
     *         <li>{@link #hash256()}</li>
     *     </ul>
     * </p>
     *
     * @param contractType     数据契约类型
     * @param annoContract     数据契约 {@link DataContract}
     * @param arrayConstructor 构造函数列表
     * @return {@link DataContractEncoder}
     */
    private @NotNull DataContractEncoder resolveEncoder(Class<?> contractType, DataContract annoContract, Function<Integer, ?> arrayConstructor) {
        DataContractEncoder encoder = typeMap.get(contractType);
        if (encoder != null) {
            return encoder;
        }
        if (!contractType.isInterface()) {
            throw new IllegalArgumentException(
                    "The registering contract type is not a interface! --"
                            + contractType.getName()
            );
        }
        // 解析获得数据契约的所有有序的字段列表
        List<FieldDeclaredInfo> allFields = resolveContractFields(contractType, annoContract);

        // 解析每一个字段，生成字段的编码器和二进制片段描述符
        int size = allFields.size();
        FieldSpecificationInfo[] fieldSpecificationInfos = new FieldSpecificationInfo[size];
        BinarySliceSpecification[] binarySliceSpecifications = new BinarySliceSpecification[size + 1];
        FieldEncoder[] fieldEncoders = new FieldEncoder[size];

        binarySliceSpecifications[0] = HEAD_SLICE;

        // 用于计算 DataContract 的版本号的哈希
        MessageDigest versionHash = hash256();
        int i = 0;
        for (FieldDeclaredInfo fieldDeclaredInfo : allFields) {
            fieldSpecificationInfos[i] = fieldDeclaredInfo.fieldSpecificationInfo;
            // 构建二进制片段
            binarySliceSpecifications[i + 1] = buildSlice(fieldDeclaredInfo.fieldSpecificationInfo);
            fieldEncoders[i] = buildFieldEncoder(fieldDeclaredInfo, binarySliceSpecifications[i + 1]);
            // 按顺序计算字段的类型
            byte[] fieldType = generateFieldTypeCode(fieldDeclaredInfo.fieldSpecificationInfo);
            versionHash.update(fieldType);

            i++;
        }

        // 数据契约的版本号取自对所有字段数据类型的哈希前 8 位
        byte[] allFieldsTypeHash = versionHash.digest();
        long version = BytesUtils.toLong(allFieldsTypeHash);

        HeaderEncoder headerEncoder = new HeaderEncoder(HEAD_SLICE, annoContract.code(), version, annoContract.name(), annoContract.description());
        DataSpecificationInfo dataSpecificationInfo = new DataSpecificationInfo(annoContract.code(), version, annoContract.name(), annoContract.description(), binarySliceSpecifications, fieldSpecificationInfos);
        return new DataContractEncoderImpl(contractType, dataSpecificationInfo, headerEncoder, fieldEncoders, arrayConstructor);
    }

    /**
     * <p>解析获得数据契约字段的有序的字段列表</p>
     * <p>
     * 该方法调用了
     *     <ul>
     *         <li>{@link #resolveFieldSpecification(Method, DataField)}</li>
     *         <li>{@link #computeExtensionDistance(Class, Class)}</li>
     *     </ul>
     * </p>
     *
     * @param contractType 数据契约字段类型
     * @param annoContract 数据契约 {@link DataContract}
     * @return {@link FieldDeclaredInfo} 的 {@link List}
     */
    private @NotNull List<FieldDeclaredInfo> resolveContractFields(@NotNull Class<?> contractType, DataContract annoContract) {
        Map<Class<?>, DeclaredFieldGroup> declaredFieldGroupMap = new HashMap<>();
        Method[] methods = contractType.getMethods();
        for (Method method : methods) {
            DataField annoField = method.getAnnotation(DataField.class);
            if (annoField == null) {
                continue;
            }
            if (method.isDefault()) {
                continue;
            }
            Class<?> declaredType = method.getDeclaringClass();
            DeclaredFieldGroup group = declaredFieldGroupMap.get(declaredType);
            if (group != null) {
                // group 不存在
                FieldSpecificationInfo fieldSpecificationInfo = resolveFieldSpecification(method, annoField);
                group.addField(method, annoField, fieldSpecificationInfo);
                continue;
            }
            if (declaredType == contractType) {
                // 字段由当前数据契约类型所声明
                FieldSpecificationInfo fieldSpecificationInfo = resolveFieldSpecification(method, annoField);
                group = new DeclaredFieldGroup(contractType, annoContract, method, annoField, fieldSpecificationInfo);
                declaredFieldGroupMap.put(contractType, group);
                continue;
            }
            // 字段由父接口声明，所以取父接口上的标注定义进行解析
            DataContract declaredContractAnnotation = declaredType.getAnnotation(DataContract.class);
            if (declaredContractAnnotation == null) {
                throw new DataContractException(
                        "Declare data contract field in a non-data-contract type! --[Type="
                                + declaredType.getName() + "]");
            }
            FieldSpecificationInfo fieldSpecificationInfo = resolveFieldSpecification(method, annoField);
            group = new DeclaredFieldGroup(declaredType, declaredContractAnnotation, method, annoField, fieldSpecificationInfo);
            declaredFieldGroupMap.put(declaredType, group);
        }

        int groupsSize = declaredFieldGroupMap.size();
        DeclaredFieldGroup[] groups = declaredFieldGroupMap.values().toArray(new DeclaredFieldGroup[groupsSize]);
        for (DeclaredFieldGroup group : groups) {
            int extensionDistance = computeExtensionDistance(contractType, group.declaredContractType);
            if (extensionDistance < 0) {
                throw new IllegalStateException("Illegal state that isn't expected to occur!");
            }
            group.setExtensionDistance(extensionDistance);
        }
        // 按照继承距离和数据契约的编码进行倒序排序，如果继承距离相同，则编码小的在前面
        // 达到的效果：父接口声明的字段在前，子接口声明的字段在后，同一个继承级别编码小的在前
        Arrays.sort(groups,
                (g1, g2) -> (g2.extensionDistance == g1.extensionDistance
                        ? g1.declaredContractAnnotation.code() - g2.declaredContractAnnotation.code()
                        : g2.extensionDistance - g1.extensionDistance
                ));
        List<FieldDeclaredInfo> allFields = new ArrayList<>();
        for (DeclaredFieldGroup group : groups) {
            allFields.addAll(group.getFields());
        }
        return allFields;
    }

    /**
     * <p>解析获得数据契约格式标准</p>
     * <p>
     * 该方法调用了
     *     <ul>
     *         <li>{@link #verifyPrimitiveType(PrimitiveType, Class, Method)}</li>
     *         <li>{@link #resolveContract(Class)}</li>
     *         <li>{@link #resolveEnumContract(Class, EnumContract)}</li>
     *     </ul>
     * </p>
     *
     * @param accessor  方法 {@link Method}
     * @param annoField 数据契约字段 {@link DataField}
     * @return {@link FieldSpecificationInfo}
     */
    private @NotNull FieldSpecificationInfo resolveFieldSpecification(Method accessor, @NotNull DataField annoField) {
        String name = annoField.name();
        name = name == null ? null : name.trim();
        if (name == null || name.length() > 0) {
            name = accessor.getName();
        }
        String description = annoField.description();
        description = description == null ? null : description.trim();

        int order = annoField.order();
        boolean repeatable = annoField.list();

        Class<?> dataType = accessor.getReturnType();

        if (repeatable) {
            if (!dataType.isArray()) {
                throw new DataContractException(
                        "The annotated repeatable type mismatch non-array type["
                                + dataType.getName() + "]! --[Field=" + accessor + "]"
                );
            }
            dataType = dataType.getComponentType();
        }

        int maxSize = annoField.maxSize();
        PrimitiveType primitiveType = annoField.primitiveType();
        if (primitiveType != null) {
            primitiveType = verifyPrimitiveType(primitiveType, dataType, accessor);
        }
        boolean refEnum = annoField.refEnum();
        EnumSpecification enumSpecification = null;
        if (refEnum) {
            EnumContract annoEnumContract = dataType.getAnnotation(EnumContract.class);
            if (annoEnumContract == null) {
                throw new DataContractException(
                        "The data type of annotated enum field is not a EnumContract! --[Field="
                                + accessor + "]");
            }
            enumSpecification = resolveEnumContract(dataType, annoEnumContract);
        }
        boolean refContract = annoField.refContract();
        DataSpecification contractSpecification = null;
        if (refContract) {
            ContractTypeVersionContext contractContext = resolveContract(dataType);
            DataContractEncoder encoder = contractContext.contractEncoder;
            contractSpecification = encoder.getSpecification();
        }
        if (primitiveType == null && enumSpecification == null && contractSpecification == null) {
            throw new DataContractException(
                    "Miss data type definition of field! --[Field=" + accessor + "]");
        }
        FieldSpecificationInfo fieldSpecificationInfo;
        if (primitiveType != null) {
            fieldSpecificationInfo = new FieldSpecificationInfo(order, name, description, primitiveType, annoField.numberEncoding(), repeatable, maxSize, dataType);
        } else if (enumSpecification != null) {
            fieldSpecificationInfo = new FieldSpecificationInfo(order, name, description, enumSpecification, repeatable, dataType);
        } else {
            fieldSpecificationInfo = new FieldSpecificationInfo(order, name, description, contractSpecification, repeatable, dataType, annoField.genericContract());
        }
        return fieldSpecificationInfo;
    }

    /**
     * 解析枚举类型数据契约
     *
     * @param dataType         数据类型
     * @param annoEnumContract 枚举类型数据契约 {@link EnumContract}
     * @return {@link EnumSpecification}
     */
    private @NotNull EnumSpecification resolveEnumContract(Class<?> dataType, EnumContract annoEnumContract) {
        EnumSpecificationInfo enumSpecificationInfo = (EnumSpecificationInfo) enumSpecificationMap.get(dataType);
        if (enumSpecificationInfo != null) {
            return enumSpecificationInfo;
        }
        try {
            if (!dataType.isEnum()) {
                throw new DataContractException("Field's type is not a enum type! --[" + dataType + "]");
            }
            Field codeField = dataType.getField("CODE");
            //if (codeField == null) {
            //    throw new DataContractException("Enum type miss the 'CODE' field! --[" + dataType.toString() + "]");
            //}
            EnumField fieldAnno = codeField.getAnnotation(EnumField.class);
            if (fieldAnno == null) {
                throw new DataContractException("Enum's 'CODE' field is not annotated with @EnumField !");
            }
            // TODO: 暂时未实现枚举契约的版本号计算
            long version = 0;
            enumSpecificationInfo = new EnumSpecificationInfo(fieldAnno.type(), annoEnumContract.code(), version,
                    annoEnumContract.name(), annoEnumContract.description(), codeField.getType());
            // get enum constants and CODE
            Object[] enumItems = dataType.getEnumConstants();
            for (Object item : enumItems) {
                int code = codeField.getInt(item);
                EnumSpecificationInfo.EnumConstant constant = new EnumSpecificationInfo.EnumConstant(code, item.toString(), item);
                enumSpecificationInfo.addConstant(constant);
            }
            enumSpecificationMap.put(dataType, enumSpecificationInfo);
            return enumSpecificationInfo;
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new DataContractException(e.getMessage(), e);
        }
    }

    /**
     * 生成字段类型编码
     *
     * @param fieldSpecificationInfo 数据契约字段格式标准
     * @return 编码 byte[]
     */
    private static byte @NotNull [] generateFieldTypeCode(@NotNull FieldSpecificationInfo fieldSpecificationInfo) {
        byte repeatable = fieldSpecificationInfo.isRepeatable() ? REPEATABLE_TYPE : SINGLE_TYPE;
        byte[] codeBytes;
        if (fieldSpecificationInfo.getPrimitiveType() != null) {
            // repeatable + type indicator + code of primitive type;
            // 1 + 1 + 4;
            codeBytes = new byte[6];
            codeBytes[0] = repeatable;
            codeBytes[1] = PRIMITIVE_TYPE_FIELD;
            BytesUtils.toBytes(fieldSpecificationInfo.getPrimitiveType().CODE, codeBytes, 2);
        } else if (fieldSpecificationInfo.getRefEnum() != null) {
            // repeatable + type indicator + code of enum contract + version of enum
            // contract;
            // 1+ 1 + 4 + 8;
            codeBytes = new byte[14];
            codeBytes[0] = repeatable;
            codeBytes[1] = ENUM_CONTRACT_FIELD;
            EnumSpecification enumSpecification = fieldSpecificationInfo.getRefEnum();
            BytesUtils.toBytes(enumSpecification.getCode(), codeBytes, 2);
            BytesUtils.toBytes(enumSpecification.getVersion(), codeBytes, 6);
        } else if (fieldSpecificationInfo.getRefContract() != null) {
            // repeatable + type indicator + code of enum contract + version of enum
            // contract;
            // 1+ 1 + 4 + 8;
            DataSpecification dataSpec = fieldSpecificationInfo.getRefContract();
            codeBytes = new byte[14];
            codeBytes[0] = repeatable;
            if (fieldSpecificationInfo.isGenericContract()) {
                codeBytes[1] = DYNAMIC_CONTRACT_FIELD;
            } else {
                codeBytes[1] = DATA_CONTRACT_FIELD;
            }
            BytesUtils.toBytes(dataSpec.getCode(), codeBytes, 2);
            BytesUtils.toBytes(dataSpec.getVersion(), codeBytes, 6);
        } else {
            throw new DataContractException("Unknown field type!");
        }
        return codeBytes;
    }

    /**
     * 验证指定的类型是否正确
     *
     * @param primitiveType 基本类型 {@link PrimitiveType}
     * @param dataType      数据类型 {@link Class}
     * @param accessor      方法 {@link Method}
     * @return {@link PrimitiveType}
     */
    private static @Nullable PrimitiveType verifyPrimitiveType(@NotNull PrimitiveType primitiveType, Class<?> dataType, Method accessor) {
        switch (primitiveType) {
            case NIL:
                return null;
            case BOOLEAN:
                if (dataType != Boolean.class && dataType != boolean.class) {
                    throw new DataContractException("The annotated primitive type[" + primitiveType
                            + "] mismatch java type[" + dataType.getName() + "]! --[Field=" + accessor.toString() + "]");
                }
                break;
            case INT8:
                if (dataType != Byte.class && dataType != byte.class) {
                    throw new DataContractException("The annotated primitive type[" + primitiveType
                            + "] mismatch java type[" + dataType.getName() + "]! --[Field=" + accessor.toString() + "]");
                }
                break;
            case INT16:
                if (dataType != Character.class && dataType != char.class && dataType != short.class) {
                    throw new DataContractException("The annotated primitive type[" + primitiveType
                            + "] mismatch java type[" + dataType.getName() + "]! --[Field=" + accessor.toString() + "]");
                }
                break;
            case INT32:
                if (dataType != Integer.class && dataType != int.class) {
                    throw new DataContractException("The annotated primitive type[" + primitiveType
                            + "] mismatch java type[" + dataType.getName() + "]! --[Field=" + accessor.toString() + "]");
                }
                break;
            case INT64:
                if (dataType != Long.class && dataType != long.class) {
                    throw new DataContractException("The annotated primitive type[" + primitiveType
                            + "] mismatch java type[" + dataType.getName() + "]! --[Field=" + accessor.toString() + "]");
                }
                break;
            case TEXT:
                if (dataType != String.class) {
                    throw new DataContractException("The annotated primitive type[" + primitiveType
                            + "] mismatch java type[" + dataType.getName() + "]! --[Field=" + accessor.toString() + "]");
                }
                break;
            case BYTES:
                if (dataType != byte[].class && (!BytesSerializable.class.isAssignableFrom(dataType))) {
                    throw new DataContractException("The annotated primitive type[" + primitiveType
                            + "] mismatch java type[" + dataType.getName() + "]! --[Field=" + accessor.toString() + "]");
                }
                break;
            default:
                throw new DataContractException("Unsupported primitive type[" + primitiveType + "] ! --[Field="
                        + accessor.toString() + "]");
        }
        return primitiveType;
    }

    /**
     * 创建二进制数据片段格式标准
     *
     * @param fieldSpecificationInfo 数据契约字段的格式标准 {@link FieldSpecificationInfo}
     * @return {@link BinarySliceSpecification}
     */
    private BinarySliceSpecification buildSlice(@NotNull FieldSpecificationInfo fieldSpecificationInfo) {
        int len = -1;
        PrimitiveType fixedValueType = null;
        PrimitiveType specPrimitiveType = fieldSpecificationInfo.getPrimitiveType();
        if (specPrimitiveType != null && specPrimitiveType != PrimitiveType.NIL) {
            NumberEncoding numberEncoding = fieldSpecificationInfo.getNumberEncoding();
            if (numberEncoding == null
                    || numberEncoding == NumberEncoding.NONE
                    || !numberEncodingConverters.containsKey(specPrimitiveType)) {
                fixedValueType = fieldSpecificationInfo.getPrimitiveType();
            }
        } else if (fieldSpecificationInfo.getRefEnum() != null) {
            fixedValueType = fieldSpecificationInfo.getRefEnum().getValueType();
        }

        boolean fixed = false;
        if (fixedValueType != null) {
            switch (fixedValueType) {
                case BOOLEAN:
                case INT8:
                    fixed = true;
                    len = 1;
                    break;
                case INT16:
                    fixed = true;
                    len = 2;
                    break;
                case INT32:
                    fixed = true;
                    len = 4;
                    break;
                case INT64:
                    fixed = true;
                    len = 8;
                    break;
                default:
                    break;
            }
        }
        if (fieldSpecificationInfo.isRepeatable()) {
            if (fixed) {
                return BinarySliceSpecification.newRepeatableFixedSlice(
                        len,
                        fieldSpecificationInfo.getName(),
                        fieldSpecificationInfo.getDescription()
                );
            } else {
                return BinarySliceSpecification.newRepeatableDynamicSlice(
                        fieldSpecificationInfo.getName(),
                        fieldSpecificationInfo.getDescription()
                );
            }
        } else {
            if (fixed) {
                return BinarySliceSpecification.newFixedSlice(
                        len,
                        fieldSpecificationInfo.getName(),
                        fieldSpecificationInfo.getDescription()
                );
            } else {
                return BinarySliceSpecification.newDynamicSlice(
                        fieldSpecificationInfo.getName(),
                        fieldSpecificationInfo.getDescription()
                );
            }
        }
    }

    /**
     * <p>创建字段编码器</p>
     * <p>
     * 该方法调用了
     *     <ul>
     *         <li>{@link #buildContractFieldEncoder(FieldDeclaredInfo, BinarySliceSpecification)}</li>
     *         <li>{@link #buildEnumFieldEncoder(FieldDeclaredInfo, BinarySliceSpecification)}</li>
     *         <li>{@link #buildPrimitiveFieldEncoder(FieldDeclaredInfo, BinarySliceSpecification)}</li>
     *     </ul>
     * </p>
     *
     * @param fieldDeclaredInfo        数据契约字段信息 {@link FieldDeclaredInfo}
     * @param binarySliceSpecification 二进制数据片段格式标准 {@link BinarySliceSpecification}
     * @return {@link FieldEncoder}
     */
    private FieldEncoder buildFieldEncoder(@NotNull FieldDeclaredInfo fieldDeclaredInfo, BinarySliceSpecification binarySliceSpecification) {
        FieldSpecificationInfo fieldSpecificationInfo = fieldDeclaredInfo.fieldSpecificationInfo;
        if (fieldSpecificationInfo.getPrimitiveType() != null) {
            return buildPrimitiveFieldEncoder(fieldDeclaredInfo, binarySliceSpecification);
        } else if (fieldSpecificationInfo.getRefEnum() != null) {
            return buildEnumFieldEncoder(fieldDeclaredInfo, binarySliceSpecification);
        } else if (fieldSpecificationInfo.getRefContract() != null) {
            return buildContractFieldEncoder(fieldDeclaredInfo, binarySliceSpecification);
        } else {
            throw new IllegalStateException(
                    "Illegal states that has no type definition for field! --[ReadMethod="
                            + fieldDeclaredInfo.reader.toString() + "]"
            );
        }
    }

    /**
     * <p>创建数据契约引用字段的编码器</p>
     * <p>该方法调用了 {@link #createFieldEncoder(BinarySliceSpecification, FieldSpecification, Method, ValueConverter)}</p>
     *
     * @param fieldDeclaredInfo        数据契约字段信息， {@link FieldDeclaredInfo}
     * @param binarySliceSpecification 二进制数据片段格式标准 {@link BinarySliceSpecification}
     * @return {@link FieldEncoder}
     */
    private FieldEncoder buildContractFieldEncoder(@NotNull FieldDeclaredInfo fieldDeclaredInfo, BinarySliceSpecification binarySliceSpecification) {
        ValueConverter valueConverter;
        Class<?> contractType = fieldDeclaredInfo.fieldSpecificationInfo.getDataType();
        if (fieldDeclaredInfo.fieldSpecificationInfo.isGenericContract()) {
            valueConverter = new DataContractGenericRefConverter(contractType, this);
        } else {
            DataContractEncoder encoder = typeMap.get(contractType);
            valueConverter = new DataContractValueConverter(encoder, encoder.getArrayConstructor());
        }
        return createFieldEncoder(binarySliceSpecification, fieldDeclaredInfo.fieldSpecificationInfo, fieldDeclaredInfo.reader, valueConverter);
    }

    /**
     * <p>创建枚举类型的字段编码器</p>
     * <p>
     * 该方法调用了
     *     <ul>
     *         <li>{@link #createFieldEncoder(BinarySliceSpecification, FieldSpecification, Method, ValueConverter)}</li>
     *         <li>{@link #generateFieldTypeCode(FieldSpecificationInfo)}</li>
     *     </ul>
     * </p>
     *
     * @param fieldDeclaredInfo        数据契约字段信息， {@link FieldDeclaredInfo}
     * @param binarySliceSpecification 二进制数据片段格式标准 {@link BinarySliceSpecification}
     * @return {@link FieldEncoder}
     */
    private FieldEncoder buildEnumFieldEncoder(@NotNull FieldDeclaredInfo fieldDeclaredInfo, BinarySliceSpecification binarySliceSpecification) {
        // 枚举类型的值转换器是由枚举值的范围检查加上一个基本类型的值转换器组成；
        Class<?> enumType = fieldDeclaredInfo.fieldSpecificationInfo.getDataType();
        EnumSpecificationInfo enumSpec = (EnumSpecificationInfo) fieldDeclaredInfo.fieldSpecificationInfo.getRefEnum();
        int[] values = enumSpec.getItemValues();
        Object[] constants = enumSpec.getConstants();
        PrimitiveType codeType = enumSpec.getValueType();

        ValueConverter baseConverter = getPrimitiveTypeConverter(codeType, enumSpec.getDataType(), null);

        EnumValueConverter valueConverter = new EnumValueConverter(
                enumType, codeType, values, constants,
                (FixedValueConverter) baseConverter
        );

        return createFieldEncoder(binarySliceSpecification, fieldDeclaredInfo.fieldSpecificationInfo, fieldDeclaredInfo.reader, valueConverter);
    }

    /**
     * <p>创建基本类型字段的编码器</p>
     * <p>
     * 该方法调用了
     *     <ul>
     *         <li>{@link #createFieldEncoder(BinarySliceSpecification, FieldSpecification, Method, ValueConverter)}</li>
     *         <li>{@link #generateFieldTypeCode(FieldSpecificationInfo)}</li>
     *     </ul>
     * </p>
     *
     * @param fieldDeclaredInfo        数据契约字段信息， {@link FieldDeclaredInfo}
     * @param binarySliceSpecification 二进制数据片段格式标准 {@link BinarySliceSpecification}
     * @return {@link FieldEncoder}
     */
    private FieldEncoder buildPrimitiveFieldEncoder(@NotNull FieldDeclaredInfo fieldDeclaredInfo, BinarySliceSpecification binarySliceSpecification) {
        ValueConverter valueConverter = getPrimitiveTypeConverter(
                fieldDeclaredInfo.fieldSpecificationInfo.getPrimitiveType(),
                fieldDeclaredInfo.fieldSpecificationInfo.getDataType(),
                fieldDeclaredInfo.fieldSpecificationInfo.getNumberEncoding()
        );
        return createFieldEncoder(binarySliceSpecification, fieldDeclaredInfo.fieldSpecificationInfo, fieldDeclaredInfo.reader, valueConverter);
    }

    /**
     * 获取基本类型的转换器
     *
     * @param protoType      基本类型
     * @param javaType       对应的 java 类
     * @param numberEncoding 数值编码格式 {@link NumberEncoding}
     * @return {@link ValueConverter}
     */
    private @NotNull ValueConverter getPrimitiveTypeConverter(
            PrimitiveType protoType,
            Class<?> javaType,
            NumberEncoding numberEncoding) {
        if (numberEncoding != null && numberEncoding != NumberEncoding.NONE) {
            Map<Class<?>, Map<NumberMask, ValueConverter>> typeConverters = numberEncodingConverters.get(protoType);
            if (typeConverters != null) {
                Map<NumberMask, ValueConverter> encodingConverters = typeConverters.get(javaType);
                if (encodingConverters != null) {
                    ValueConverter converter = encodingConverters.get(numberEncoding.MASK);
                    if (converter != null) {
                        return converter;
                    }
                }
            }
        }
        Map<Class<?>, ValueConverter> converterMap = primitiveTypeConverters.get(protoType);
        if (converterMap != null) {
            ValueConverter converter = converterMap.get(javaType);
            if (converter != null) {
                return converter;
            }
            if (PrimitiveType.BYTES == protoType && BytesSerializable.class.isAssignableFrom(javaType)) {
                converter = new BytesSerializableValueConverter(javaType);
                converterMap.put(javaType, converter);
                return converter;
            }
        }
        throw new IllegalArgumentException(String.format("Unsupported types mapping: [PrimitiveType=%s]-[JavaType=%s]",
                protoType.toString(), javaType.toString()));
    }

    /**
     * <p>创建字段编码器</p>
     * <p>
     * 该方法调用了
     *     <ul>
     *         <li>{@link #createDynamicArrayFieldEncoder(BinarySliceSpecification, FieldSpecification, Method, DynamicValueConverter)}</li>
     *         <li>{@link #createFixedArrayFieldEncoder(BinarySliceSpecification, FieldSpecification, Method, FixedValueConverter)}</li>
     *     </ul>
     * </p>
     *
     * @param binarySliceSpecification 二进制数据片段格式标准 {@link BinarySliceSpecification}
     * @param fieldSpecification       数据契约字段格式标准 {@link FieldSpecification}
     * @param reader                   方法（Get方法） {@link Method}
     * @param valueConverter           值转换器 {@link ValueConverter}
     * @return {@link FieldEncoder}
     */
    private static FieldEncoder createFieldEncoder(
            @NotNull BinarySliceSpecification binarySliceSpecification,
            FieldSpecification fieldSpecification,
            Method reader,
            ValueConverter valueConverter) {
        if (binarySliceSpecification.isRepeatable()) {
            if (binarySliceSpecification.isDynamic()) {
                return createDynamicArrayFieldEncoder(binarySliceSpecification, fieldSpecification, reader, (DynamicValueConverter) valueConverter);
            } else {
                return createFixedArrayFieldEncoder(binarySliceSpecification, fieldSpecification, reader, (FixedValueConverter) valueConverter);
            }
        } else {
            if (binarySliceSpecification.isDynamic()) {
                return new DynamicFieldEncoder(binarySliceSpecification, fieldSpecification, reader, (DynamicValueConverter) valueConverter);
            } else {
                return new FixedFieldEncoder(binarySliceSpecification, fieldSpecification, reader, (FixedValueConverter) valueConverter);
            }
        }
    }

    /**
     * <p>创建动态数组编码器</p>
     * <p>
     * 动态数组编码器有：
     *     <ul>
     *         <li>{@link DynamicArrayFieldEncoder}</li>
     *         <li>{@link DynamicByteArrayFieldEncoder}</li>
     *         <li>{@link DynamicShortArrayFieldEncoder}</li>
     *         <li>{@link DynamicCharArrayFieldEncoder}</li>
     *         <li>{@link DynamicIntArrayFieldEncoder}</li>
     *         <li>{@link DynamicLongArrayFieldEncoder}</li>
     *         <li>{@link DynamicObjectArrayFieldEncoder}</li>
     *     </ul>
     * </p>
     *
     * @param binarySliceSpecification 二进制数据片段格式标准 {@link BinarySliceSpecification}
     * @param fieldSpecification       数据契约字段格式标准 {@link FieldSpecification}
     * @param reader                   方法（Get方法） {@link Method}
     * @param valueConverter           值转换器 {@link ValueConverter}
     * @return {@link FieldEncoder}
     */
    @Contract("_, _, _, _ -> new")
    private static @NotNull DynamicArrayFieldEncoder createDynamicArrayFieldEncoder(
            BinarySliceSpecification binarySliceSpecification,
            FieldSpecification fieldSpecification,
            @NotNull Method reader,
            DynamicValueConverter valueConverter) {
        Class<?> returnType = reader.getReturnType();
        if (!returnType.isArray()) {
            throw new IllegalArgumentException("The return type of Filed["
                    + reader.getName() + "] is not array type!");
        }
        Class<?> componentType = returnType.getComponentType();
        if (!componentType.isPrimitive()) {
            return new DynamicObjectArrayFieldEncoder(binarySliceSpecification, fieldSpecification, reader, valueConverter);
        }
        if (long.class == componentType) {
            return new DynamicLongArrayFieldEncoder(binarySliceSpecification, fieldSpecification, reader, valueConverter);
        }
        if (int.class == componentType) {
            return new DynamicIntArrayFieldEncoder(binarySliceSpecification, fieldSpecification, reader, valueConverter);
        }
        if (short.class == componentType) {
            return new DynamicShortArrayFieldEncoder(binarySliceSpecification, fieldSpecification, reader, valueConverter);
        }
        if (char.class == componentType) {
            return new DynamicCharArrayFieldEncoder(binarySliceSpecification, fieldSpecification, reader, valueConverter);
        }
        if (byte.class == componentType) {
            return new DynamicByteArrayFieldEncoder(binarySliceSpecification, fieldSpecification, reader, valueConverter);
        }

        return new DynamicArrayFieldEncoder(binarySliceSpecification, fieldSpecification, reader, valueConverter);
    }

    /**
     * <p>创建静态数组编码器</p>
     * <p>
     * 静态数组编码器有：
     *     <ul>
     *         <li>{@link FixedArrayFieldEncoder}</li>
     *         <li>{@link FixedByteArrayFieldEncoder}</li>
     *         <li>{@link FixedShortArrayFieldEncoder}</li>
     *         <li>{@link FixedCharArrayFieldEncoder}</li>
     *         <li>{@link FixedIntArrayFieldEncoder}</li>
     *         <li>{@link FixedLongArrayFieldEncoder}</li>
     *         <li>{@link FixedObjectArrayFieldEncoder}</li>
     *     </ul>
     * </p>
     *
     * @param binarySliceSpecification 二进制数据片段格式标准 {@link BinarySliceSpecification}
     * @param fieldSpecification       数据契约字段格式标准 {@link FieldSpecification}
     * @param reader                   方法（Get方法） {@link Method}
     * @param valueConverter           值转换器 {@link ValueConverter}
     * @return {@link FieldEncoder}
     */
    @Contract("_, _, _, _ -> new")
    private static @NotNull FixedArrayFieldEncoder createFixedArrayFieldEncoder(
            BinarySliceSpecification binarySliceSpecification,
            FieldSpecification fieldSpecification,
            @NotNull Method reader,
            FixedValueConverter valueConverter) {
        // 判断返回值数组的类型，创建相应的数组类型的转换器；
        Class<?> returnType = reader.getReturnType();
        if (!returnType.isArray()) {
            throw new IllegalArgumentException("The return type of Filed[" + reader.getName() + "] is not array type!");
        }
        Class<?> componentType = returnType.getComponentType();
        if (!componentType.isPrimitive()) {
            return new FixedObjectArrayFieldEncoder(binarySliceSpecification, fieldSpecification, reader, valueConverter);
        }
        if (long.class == componentType) {
            return new FixedLongArrayFieldEncoder(binarySliceSpecification, fieldSpecification, reader, valueConverter);
        }
        if (int.class == componentType) {
            return new FixedIntArrayFieldEncoder(binarySliceSpecification, fieldSpecification, reader, valueConverter);
        }
        if (short.class == componentType) {
            return new FixedShortArrayFieldEncoder(binarySliceSpecification, fieldSpecification, reader, valueConverter);
        }
        if (char.class == componentType) {
            return new FixedCharArrayFieldEncoder(binarySliceSpecification, fieldSpecification, reader, valueConverter);
        }
        if (byte.class == componentType) {
            return new FixedByteArrayFieldEncoder(binarySliceSpecification, fieldSpecification, reader, valueConverter);
        }

        return new FixedArrayFieldEncoder(binarySliceSpecification, fieldSpecification, reader, valueConverter);
    }


    /**
     * 计算两个指定接口类型之间的继承距离，如果不具有继承关系，返回 -1
     *
     * @param subsTypes 子类型
     * @param superType 父类型
     * @return int 值
     */
    private static int computeExtensionDistance(Class<?> subsTypes, Class<?> superType) {
        if (subsTypes == superType) {
            return 0;
        }
        Class<?>[] superInterfaces = subsTypes.getInterfaces();
        for (Class<?> c : superInterfaces) {
            int distance = computeExtensionDistance(c, superType);
            if (distance > -1) {
                return distance + 1;
            }
        }
        return -1;
    }

    /**
     * <h1>数据契约字段簇</h1>
     * <p>以 {@link TreeMap} 数据结构来存储 {@link FieldDeclaredInfo}</p>
     */
    private static class DeclaredFieldGroup {

        /**
         * 声明的数据契约类型
         */
        private Class<?> declaredContractType;

        /**
         * 声明的数据契约
         */
        private DataContract declaredContractAnnotation;

        /**
         * <p>声明类型距离要解析的类型的继承距离</p>
         * <p>直接继承的父接口的距离为 1，父接口的父接口距离为 2，依此类推</p>
         */
        private int extensionDistance;

        /**
         * 字段信息的 {@link TreeMap}
         */
        private TreeMap<Integer, FieldDeclaredInfo> orderedFields = new TreeMap<>();

        @Contract(pure = true)
        public @NotNull Collection<FieldDeclaredInfo> getFields() {
            return orderedFields.values();
        }

        public DeclaredFieldGroup(Class<?> declaredContractType, DataContract declaredContractAnnotation,
                                  Method accessor, DataField fieldAnnotation, FieldSpecificationInfo fieldSpecificationInfo) {
            this.declaredContractType = declaredContractType;
            this.declaredContractAnnotation = declaredContractAnnotation;

            addField(accessor, fieldAnnotation, fieldSpecificationInfo);
        }

        /**
         * 添加字段
         *
         * @param accessor               {@link Method} 字段的 Get 方法
         * @param fieldAnnotation        {@link DataField} 数据契约字段
         * @param fieldSpecificationInfo {@link FieldSpecificationInfo} 数据契约格式标准
         */
        private void addField(Method accessor, DataField fieldAnnotation, FieldSpecificationInfo fieldSpecificationInfo) {
            // 检查字段是否有重复序号
            FieldDeclaredInfo fieldInfo = new FieldDeclaredInfo(accessor, fieldAnnotation, fieldSpecificationInfo);
            FieldDeclaredInfo conflictedField = orderedFields.put(fieldSpecificationInfo.getOrder(), fieldInfo);
            if (conflictedField != null) {
                throw new DataContractException(String.format(
                        "Declare two fields with the same order! --[%s][%s]",
                        fieldInfo.reader.toString(),
                        conflictedField.reader.toString()
                ));
            }
        }

        public int getExtensionDistance() {
            return extensionDistance;
        }

        public void setExtensionDistance(int extensionDistance) {
            this.extensionDistance = extensionDistance;
        }
    }

    /**
     * <h1>数据契约字段信息</h1>
     */
    private static class FieldDeclaredInfo {

        private FieldSpecificationInfo fieldSpecificationInfo;

        private Method reader;

        private DataField annoField;

        public FieldDeclaredInfo(Method accessor, DataField annoField, FieldSpecificationInfo fieldSpec) {
            this.reader = accessor;
            this.annoField = annoField;
            this.fieldSpecificationInfo = fieldSpec;
        }
    }

    /**
     * <h1>数据契约的类型版本环境</h1>
     */
    private static class ContractTypeVersionContext {

        private Class<?> contractType;

        private DataContractEncoder contractEncoder;

        public ContractTypeVersionContext(Class<?> contractType, DataContractEncoder contractEncoder) {
            this.contractType = contractType;
            this.contractEncoder = contractEncoder;
        }
    }

    /**
     * 获取 SHA-256 的 {@link MessageDigest}
     *
     * @return {@link MessageDigest}
     */
    private static MessageDigest hash256() {
        try {
            return MessageDigest.getInstance("SHA-256");
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }
}
